/**
 * 
 */
package net.looker.util;

/**
 * 对象队列
 * 用于安全的保证对象的并发访问
 * 用于保存多个线程对象
 * @author solosky
 *
 */
public class BlockQueue<E>
{
	/**
	 * 工作对象数组,使用循环队列保存对象
	 */
	protected Object[] Objects;
	
	/**
	 * 队列最大容量
	 */
	protected int capacity;
	
	/**
	 * 队列当前大小
	 */
	protected int size;
	
	/**
	 * 队列头
	 */
	protected int head;
	
	/**
	 * 队列尾部
	 */
	protected int tail;
	
	/**
	 * 构造函数 建立一个指定大小的队列
	 * @param int capacity
	 */
	public BlockQueue(int capacity)
	{
		this.capacity = capacity>0 ? capacity : 1;	//至少有一个元素
		this.Objects  = new Object[this.capacity];
		head          = 0;
		tail          = 0;
		size          = 0;
	}
	
	/**
	 * 得到队列容量
	 * @return int capacity
	 */
	public int getCapacity()
	{
		return this.capacity;
	}
	
	/**
	 * 得到队列当前大小
	 * @return int size
	 */
	public synchronized int getSize()
	{
		return this.size;
	}
	
	/**
	 * 判断是否为空
	 * @return boolean
	 */
	public synchronized boolean isEmpty()
	{
		return (size==0);
	}
	
	/**
	 * 判断是否为空
	 * @return boolean
	 */
	public synchronized boolean isFull()
	{
		return (size==capacity);
	}
	
	/**
	 * 等待直到队列为空
	 * @throws InterruptedException 
	 */
	public synchronized void waitUntilEmpty() throws InterruptedException
	{
		while ( !isEmpty() )
			wait();
	}
	
	/**
	 * 当队列空时等待
	 * @throws InterruptedException 
	 */
	public synchronized void waitWhileEmpty() throws InterruptedException 
	{
		while ( isEmpty() )
			wait();
	}
	
	/**
	 *  等待知道队列满
	 * @throws InterruptedException 
	 */
	public synchronized void waitUntilFull() throws InterruptedException
	{
		while ( !isFull() )
			wait();
	}
	
	/**
	 * 当队列满时等待
	 * @throws InterruptedException 
	 */
	public synchronized void waitWhileFull() throws InterruptedException
	{
		while ( isFull())
			wait();
	}
	
	/**
	 * 添加一个工作对象
	 * @param Object
	 * @throws InterruptedException 
	 */
	public synchronized void add(E Object) throws InterruptedException
	{
		//等待，当队列为空的时候等待
		waitWhileFull();
		
		//添加工作对象至队列头
		Objects[head] = Object;
		//改变头指针
		head = (head+1) % capacity;
		//增加队列长度
		size++;
		
		//通知其他等待变化的线程，添加了对象
		notifyAll();
	}
	
	/**
	 * 在队尾删除一个工作对象
	 * @throws InterruptedException 
	 */
	public synchronized E remove() throws InterruptedException
	{
		//在队列为空的时候等待
		waitWhileEmpty();
		
		//获得队尾元素
		Object Object =  Objects[tail];
		//删除队尾元素，去掉引用保证GC的能安全的删除对象
		Objects[tail] = null;
		//更新队尾指针
		tail = (tail+1) % capacity;
		//减少队列大小
		size--;
		
		//通知其他等待的线程对象的值已经发生改变
		notifyAll();
		
		//返回工作对象
		return (E) Object;
	}
	
	/**
	 * 返回队尾第一个元素，但不删除
	 * @throws InterruptedException 
	 */
	public synchronized E first() throws InterruptedException
	{
		//在队列为空的时候等待
		waitWhileEmpty();
		
		//获得队尾元素
		Object Object =  Objects[tail];
		//返回工作对象
		return (E) Object;
	}
	
}
